/*
 * 22/10/2011 - 11:45
 */
package org.nettyflux.remote;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.nettyflux.communicator.RemoteHost;
import org.nettyflux.mailbox.MailBox;
import org.nettyflux.netmessages.NetworkMessage;

/**
 * @author Victor Williams Stafusa da Silva
 */
public class StubFactory {

    private final StubStrategy strategy;
    private final MailBox<NetworkMessage> mailbox;

    public StubFactory(StubStrategy strategy, MailBox<NetworkMessage> mailbox) {
        this.strategy = strategy;
        this.mailbox = mailbox;
    }

    private class StubProxy implements InvocationHandler {

        private final RemoteHost node;
        private final String objectName;

        public StubProxy(String objectName, RemoteHost node) {
            this.node = node;
            this.objectName = objectName;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return strategy.handle(mailbox, objectName, node, proxy, method, args);
        }
    }

    public <E> E makeStub(
            String objectName,
            RemoteHost target,
            Class<E> anInterface)
    {
        return anInterface.cast(Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class<?>[] {anInterface},
                new StubProxy(objectName, target)));
    }

    public Object makeStub(
            String objectName,
            RemoteHost target,
            Class<?>... interfaces)
    {
        return Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                interfaces,
                new StubProxy(objectName, target));
    }
}
